package com.yic.module.mes.service.modetail;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.yic.module.mes.dal.dataobject.mo.MoDO;
import com.yic.module.mes.dal.dataobject.moroute.MoRouteDO;
import com.yic.module.system.enums.dict.MesSerialTypeEnum;
import com.yic.module.system.enums.dict.WmsItemTypeEnum;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import com.yic.module.mes.controller.admin.modetail.vo.*;
import com.yic.module.mes.dal.dataobject.modetail.MoDetailDO;
import com.yic.framework.common.pojo.PageResult;

import com.yic.module.mes.convert.modetail.MoDetailConvert;
import com.yic.module.mes.dal.mysql.modetail.MoDetailMapper;

import static com.yic.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.yic.module.mes.enums.ErrorCodeConstants.*;

/**
 * 工单明细 Service 实现类
 *
 * @author 系统管理员
 */
@Service
@Validated
public class MoDetailServiceImpl implements MoDetailService {

    @Resource
    private MoDetailMapper moDetailMapper;

    @Override
    public Long createMoDetail(MoDetailCreateReqVO createReqVO) {
        // 插入
        MoDetailDO moDetail = MoDetailConvert.INSTANCE.convert(createReqVO);
        moDetailMapper.insert(moDetail);
        // 返回
        return moDetail.getId();
    }

    @Override
    public void batchCreateMoDetail(List<MoDetailDO> list) {
        moDetailMapper.insertBatch(list);
    }

    @Override
    public void updateMoDetail(MoDetailUpdateReqVO updateReqVO) {
        // 校验存在
        validateMoDetailExists(updateReqVO.getId());
        // 更新
        MoDetailDO updateObj = MoDetailConvert.INSTANCE.convert(updateReqVO);
        moDetailMapper.updateById(updateObj);
    }

    @Override
    public void deleteMoDetail(Long id) {
        // 校验存在
        validateMoDetailExists(id);
        // 删除
        moDetailMapper.deleteById(id);
    }

    private void validateMoDetailExists(Long id) {
        if (moDetailMapper.selectById(id) == null) {
            throw exception(MO_DETAIL_NOT_EXISTS);
        }
    }

    @Override
    public MoDetailDO getMoDetail(Long id) {
        return moDetailMapper.selectById(id);
    }

    @Override
    public List<MoDetailDO> getMoDetailList(Collection<Long> ids) {
        return moDetailMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<MoDetailDO> getMoDetailPage(MoDetailPageReqVO pageReqVO) {
        return moDetailMapper.selectPage(pageReqVO);
    }

    @Override
    public List<MoDetailDO> getMoDetailList(MoDetailExportReqVO exportReqVO) {
        return moDetailMapper.selectList(exportReqVO);
    }

    private List<MoDetailDO> generateMoDetail(Long factoryId, Long moId, BigDecimal produceAmount) {
        int amount = produceAmount.intValueExact();
        List<MoDetailDO> list = new ArrayList<>(amount);
        String dateStr = DateUtil.format(LocalDateTime.now(), DatePattern.PURE_DATE_PATTERN);
        for (int i = 0; i < amount; i++) {
            String serial = String.format("%06d", i+1);
            String sn = StrUtil.format("{}|{}|{}|{}|{}", factoryId, WmsItemTypeEnum.PRODUCE.getWmsItemType(), moId, dateStr, serial);
            MoDetailDO moDetailDO = new MoDetailDO();
            moDetailDO.setMoId(moId);
            moDetailDO.setMoSn(sn);
            moDetailDO.setItemSn(sn);
            list.add(moDetailDO);
        }
        return list;
    }

    @Override
    public void deleteMoDetailByMoId(Long moId) {
        moDetailMapper.deleteByMoId(moId);
    }

    @Override
    public void batchCreateMoDetail(List<MoDO> mos, Integer snType, Long factoryId) {
        List<MoDetailDO> list = new ArrayList<>();
        if (snType.equals(MesSerialTypeEnum.AUTO.getMesSerialType())) { //自动生成流水号
            mos.forEach(moDO -> {
                List<MoDetailDO> moDetailDOS = generateMoDetail(factoryId, moDO.getId(), moDO.getProduceAmount());
                list.addAll(moDetailDOS);
            });
        } else if(snType.equals(MesSerialTypeEnum.CUSTOM.getMesSerialType())) { //自定义流水号
            mos.forEach(moDO -> {
                String moSns = moDO.getMoSns();
                String[] arr = moSns.split("\n");
                if (arr.length != moDO.getProduceAmount().intValue()) {
                    throw exception(MO_DETAIL_NOT_EQUAL_PRODUCE_AMOUNT, moDO.getCode());
                }
                for (int i = 0; i < arr.length; i++) {
                    MoDetailDO moDetailDO = new MoDetailDO();
                    moDetailDO.setMoId(moDO.getId());
                    moDetailDO.setMoSn(arr[i]);
                    moDetailDO.setItemSn(arr[i]);
                    list.add(moDetailDO);
                }
            });
        } else { // 无流水号,无需处理

        }
        // 校验重复
        List<String> sns = list.stream().map(MoDetailDO::getMoSn).distinct().collect(Collectors.toList());
        if (sns.size() != list.size()) {
            throw exception(MO_DETAIL_NOT_REPEAT);
        }
        List<MoDetailDO> moDetailDOS = moDetailMapper.selectByMoSn(sns);
        if (CollectionUtil.isNotEmpty(moDetailDOS)) {
            throw exception(MO_DETAIL_NOT_REPEAT);
        }
        batchCreateMoDetail(list);
    }

    @Override
    public MoDetailDO getMoDetail(Long moId, String serialNo) {
        return moDetailMapper.selectByMoAndSn(moId, serialNo);
    }

    @Override
    public MoDetailDO getMoDetailBySn(String serialNo) {
        return moDetailMapper.selectBySn(serialNo);
    }

}
